package cc.siyecao.fastdfs.command;

import cc.siyecao.fastdfs.extception.FastDfsException;
import cc.siyecao.fastdfs.pool.FdfsConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;

/**
 * 交易命令抽象类
 *
 * @param <T>
 * @author lyt
 */
public abstract class AbstractFdfsCommand<T> implements FdfsCommand<T> {
    protected byte errno;
    /**
     * 日志
     */
    private static final Logger LOGGER = LoggerFactory.getLogger( AbstractFdfsCommand.class );

    /**
     * 对服务端发出请求然后接收反馈
     */
    @Override
    public T execute(FdfsConnection conn) {
        // 封装socket交易 send
        try {
            send( conn.getOutputStream(), conn.getCharset() );
        } catch (Exception e) {
            LOGGER.error( "send conent error", e );
            throw new FastDfsException( "socket io exception occured while sending cmd", e );
        }

        try {
            return receive( conn.getInputStream(), conn.getCharset() );
        } catch (Exception e) {
            LOGGER.error( "receive conent error", e );
            throw new FastDfsException( "socket io exception occured while receive content", e );
        }

    }

    /**
     * 将报文输出规范为模板方法
     * <p>
     * <pre>
     * 1.输出报文头
     * 2.输出报文参数
     * 3.输出文件内容
     * </pre>
     *
     * @param out
     * @throws IOException
     */
    protected abstract void send(OutputStream out, Charset charset) throws Exception;

    /**
     * 接收这里只能确切知道报文头，报文内容(参数+文件)只能靠接收对象分析
     *
     * @param in
     * @return
     * @throws IOException
     */
    protected abstract T receive(InputStream in, Charset charset) throws Exception;

}
